#include "pch.h"
#include "AsyncTaskImpl.h"
#include "Threadpool.h"
#include "OrderedTask.h"
#include "DelayedTask.h"
#include "UIThreadTask.h"
#include "..\Common\SRWLock.h"

CAsyncTask::CAsyncTask()
	: m_nLastTaskId(0)
	, m_bInited(false)
{
}

CAsyncTask::~CAsyncTask()
{
	assert(!m_pThreadpool);
}

bool CAsyncTask::Init()
{
	AssertInUIThread();
	assert(!m_pThreadpool);

	SYSTEM_INFO sysInfo;
	GetSystemInfo(&sysInfo);

	CExclusiveLock lock(m_SRWLock);
	m_pThreadpool = std::make_unique<CThreadpool>(sysInfo.dwNumberOfProcessors, sysInfo.dwNumberOfProcessors * 2);
	m_pOrderedTask = std::make_unique<COrderedTask>();
	m_pDelayedTask = std::make_unique<CDelayedTask>();
	m_pUIThreadTask = std::make_unique<CUIThreadTask>();

	return m_bInited =
		m_pThreadpool->Init() &&
		m_pOrderedTask->Init() &&
		m_pDelayedTask->Init() &&
		m_pUIThreadTask->Init();
}

void CAsyncTask::Exit()
{
	AssertInUIThread();

	CExclusiveLock lock(m_SRWLock);
	m_bInited = false;
	auto pThreadpool = std::move(m_pThreadpool);
	auto pOrderedTask = std::move(m_pOrderedTask);
	auto pDelayedTask = std::move(m_pDelayedTask);
	auto pUIThreadTask = std::move(m_pUIThreadTask);
	lock.Unlock();

	if (pThreadpool)
	{
		pUIThreadTask->Exit();
		pDelayedTask->Exit();
		pOrderedTask->Exit();
		pThreadpool->Exit();
	}
}

bool CAsyncTask::AsyncTask(ICallbackPtr&& pTask)
{
	if (!pTask)
		return false;

	pTask->SetId(++m_nLastTaskId);
	CSharedLock lock(m_SRWLock);
	return m_bInited && m_pThreadpool->PostTask(std::move(pTask));
}

bool CAsyncTask::OrderedTask(CValueKey key, ICallbackPtr&& pTask)
{
	if (!pTask)
		return false;

	pTask->SetId(++m_nLastTaskId);
	CSharedLock lock(m_SRWLock);
	return m_bInited && m_pOrderedTask->PostTask(key, std::move(pTask), m_pThreadpool);
}

bool CAsyncTask::DelayedTask(UINT nDelayMs, ICallbackPtr&& pTask)
{
	if (!pTask)
		return false;

	pTask->SetId(++m_nLastTaskId);
	CSharedLock lock(m_SRWLock);
	return m_bInited && m_pDelayedTask->PostTask(nDelayMs, std::move(pTask));
}

bool CAsyncTask::UIAsyncTask(ICallbackPtr&& pTask)
{
	if (!pTask)
		return false;

	pTask->SetId(++m_nLastTaskId);
	CSharedLock lock(m_SRWLock);
	return m_bInited && m_pUIThreadTask->PostTask(std::move(pTask));
}

bool CAsyncTask::UIDelayedTask(UINT nDelayMs, ICallbackPtr&& pTask)
{
	if (!pTask)
		return false;

	pTask->SetId(++m_nLastTaskId);
	CSharedLock lock(m_SRWLock);
	return m_bInited && m_pUIThreadTask->PostTask(nDelayMs, std::move(pTask));
}
